import base64
import json
import os

from rest_framework import serializers
from apiapp.models import User, UserTour, Tour
from rest_framework import validators
from rest_framework import exceptions
from g4f.client import Client
from drf_extra_fields.fields import Base64ImageField
from apiapp import utils
from datetime import timedelta


class UserRegisterSerializer(serializers.Serializer):
    first_name = serializers.CharField(max_length=200)
    last_name = serializers.CharField(max_length=200)
    email = serializers.EmailField(validators=[
        validators.UniqueValidator(queryset=User.objects.all(), message='Email already exists'),
    ])
    password = serializers.CharField(max_length=200)

    def create(self, validated_data):
        try:
            return User.objects.create_user(**validated_data, username=validated_data['email'])
        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e


class UserLoginSerializer(serializers.Serializer):
    email = serializers.EmailField()
    password = serializers.CharField(max_length=200)

    def create(self, validated_data):
        try:
            if User.objects.filter(email=validated_data['email']).exists():
                if User.objects.get(email=validated_data['email']).check_password(validated_data['password']):
                    return User.objects.get(email=validated_data['email'])
            raise exceptions.AuthenticationFailed()
        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e


class AddTourSerializer(serializers.ModelSerializer):
    description = serializers.CharField(style={'base_template': 'textarea.html'})
    image = Base64ImageField(required=True)

    class Meta:
        model = Tour
        exclude = ['isActive']
        extra_kwargs = {'arrivalDate': {'required': True}, 'departureDate': {'required': True}}

    def create(self, validated_data):
        try:
            tour = Tour.objects.create(**validated_data)
            return {
                'success': True,
                'message': 'Tour created'
            }
        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e


class GetTourSerializer(serializers.Serializer):
    def create(self, validated_data):
        try:
            if validated_data['id']:
                if Tour.objects.filter(id=validated_data['id']).exists():
                    user = validated_data.pop('user')
                    tour = Tour.objects.filter(id=validated_data['id']).first()

                    if user.is_authenticated:
                        isPaid = False
                        isBook = False
                        if UserTour.objects.filter(user=user, tour=tour).exists():
                            isBook = True
                            isPaid = UserTour.objects.filter(user=user, tour=tour).first().isPaid

                        availableSeats = tour.seats - UserTour.objects.filter(tour=tour).count()
                        image = utils.get_image_base64(tour.image)
                        return {
                            'id': tour.id,
                            'name': tour.name,
                            'description': tour.description,
                            'price': tour.price,
                            'seats': tour.seats,
                            'isActive': tour.isActive,
                            'image': image,
                            'arrivalDate': tour.arrivalDate.strftime('%d.%m.%Y %H:%M'),
                            'departureDate': tour.departureDate.strftime('%d.%m.%Y %H:%M'),
                            'availableSeats': availableSeats,
                            'isPaid': isPaid,
                            'isBook': isBook,
                        }

                    else:
                        availableSeats = tour.seats - UserTour.objects.filter(tour=tour).count()
                        image = utils.get_image_base64(tour.image)
                        return {
                            'id': tour.id,
                            'name': tour.name,
                            'description': tour.description,
                            'price': tour.price,
                            'seats': tour.seats,
                            'isActive': tour.isActive,
                            'image': image,
                            'arrivalDate': tour.arrivalDate,
                            'departureDate': tour.departureDate,
                            'availableSeats': availableSeats,
                        }

            raise exceptions.NotFound("Tour not found")

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class GetAllToursSerializer(serializers.Serializer):
    def create(self, validated_data):
        try:
            tours = Tour.objects.all()
            user = validated_data.pop('user')

            if user.is_authenticated:
                response = []
                for tour in tours:
                    isPaid = False
                    isBook = False
                    if UserTour.objects.filter(user=user, tour=tour).exists():
                        isBook = True
                        isPaid = UserTour.objects.filter(user=user, tour=tour).first().isPaid
                    availableSeats = tour.seats - UserTour.objects.filter(tour=tour).count()
                    image = utils.get_image_base64(tour.image)
                    response.append(
                        {
                            'id': tour.id,
                            'name': tour.name,
                            'description': tour.description,
                            'price': tour.price,
                            'seats': tour.seats,
                            'isActive': tour.isActive,
                            'image': image,
                            'arrivalDate': tour.arrivalDate,
                            'departureDate': tour.departureDate,
                            'availableSeats': availableSeats,
                            'isPaid': isPaid,
                            'isBook': isBook,
                        }
                    )

                return response

            else:
                response = []
                for tour in tours:
                    availableSeats = tour.seats - UserTour.objects.filter(tour=tour).count()
                    image = utils.get_image_base64(tour.image)
                    response.append(
                        {
                            'id': tour.id,
                            'name': tour.name,
                            'description': tour.description,
                            'price': tour.price,
                            'seats': tour.seats,
                            'isActive': tour.isActive,
                            'image': image,
                            'arrivalDate': tour.arrivalDate,
                            'departureDate': tour.departureDate,
                            'availableSeats': availableSeats,
                        }
                    )

                return response

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class GetUserInfoSerializer(serializers.Serializer):
    def create(self, validated_data):
        try:
            user = validated_data['user']

            return {
                'id': user.id,
                'first_name': user.first_name,
                'last_name': user.last_name,
                'email': user.email,
                'isAdmin': user.isAdmin
            }

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class TourDescriptionGenerator(serializers.Serializer):
    name = serializers.CharField(max_length=60)
    sketch = serializers.CharField(max_length=255)

    def create(self, validated_data):
        try:
            client = Client(
                # proxies='http://127.0.0.1:2081'
            )
            response = client.chat.completions.create(
                model="gpt-3.5-turbo",
                messages=[{"role": "user",
                           "content": f"Напиши описание на 3 абзаца для тура по Южному Уралу. Название тура: {validated_data['name']}. Краткое описание: {validated_data['sketch']}"}],
            )

            return ({
                'success': True,
                'message': response.choices[0].message.content,
            })

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class TourDeleteSerializer(serializers.Serializer):
    def create(self, validated_data):
        try:
            if validated_data['id']:
                if Tour.objects.filter(id=validated_data['id']).exists():
                    tour = Tour.objects.filter(id=validated_data['id']).first()
                    os.remove(tour.image.path)
                    tour.delete()
                    return {
                        'success': True,
                        'message': "Tour Deleted"
                    }

            raise exceptions.NotFound("Tour not found")

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class TourEditSerializer(serializers.ModelSerializer):
    description = serializers.CharField(style={'base_template': 'textarea.html'})
    image = Base64ImageField(required=True)

    class Meta:
        model = Tour
        exclude = ['isActive']
        extra_kwargs = {'arrivalDate': {'required': True}, 'departureDate': {'required': True}}

    def create(self, validated_data):
        try:
            if validated_data['id']:
                id = validated_data.pop('id')
                if Tour.objects.filter(id=id).exists():
                    tour = Tour.objects.filter(id=id).first()
                    for key, value in validated_data.items():
                        setattr(tour, key, value)
                    tour.save()
                    return {
                        'success': True,
                        'message': 'Tour updated'
                    }
            raise exceptions.NotFound("Tour not found")

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class TourAddBookSerializer(serializers.Serializer):
    def create(self, validated_data):
        try:
            if validated_data['id']:
                user = validated_data.pop('user')
                id = validated_data.pop('id')
                if Tour.objects.filter(id=id).exists():
                    tour = Tour.objects.filter(id=id).first()
                    UserTour.objects.create(user=user, tour=tour)
                    messageDateTime = tour.departureDate - timedelta(days=1)
                    utils.sendToTelegram(user.id, f"""
Здравствуйте!

Напоминаем, что завтра {tour.departureDate.strftime('%d.%m.%Y')}, состоится тур '{tour.name}'.

Не забудьте взять с собой паспорт.

Мы собираемся по адресу г.Челябинск, ул.Энтузиастов, д.17 в {tour.departureDate.strftime('%H:%M')}.
                """, messageDateTime.strftime("%m.%d.%Y"), tour.id)
                    return {
                        'success': True,
                        'message': 'Тур забронирован'
                    }
            raise exceptions.NotFound("Tour not found")

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class TourRemoveBookSerializer(serializers.Serializer):
    def create(self, validated_data):
        try:
            if validated_data['id']:
                user = validated_data.pop('user')
                id = validated_data.pop('id')
                if Tour.objects.filter(id=id).exists():
                    tour = Tour.objects.filter(id=id).first()
                    if UserTour.objects.filter(user=user, tour=tour).exists():
                        userTour = UserTour.objects.filter(user=user, tour=tour).first()
                        if not userTour.isPaid:
                            utils.removeMessageFromTelegram(user.id, tour.id)
                            UserTour.objects.filter(user=user, tour=tour).delete()
                            return {
                                'success': True,
                                'message': 'Бронь с тура убрана'
                            }
                    raise exceptions.PermissionDenied()

            raise exceptions.NotFound("Tour not found")

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class AllUserToursSerializer(serializers.Serializer):
    def create(self, validated_data):
        try:
            user = validated_data.pop('user')
            tours = user.tours.all()

            response = []
            for tour in tours:
                image = utils.get_image_base64(tour.image)
                isPaid = UserTour.objects.filter(user=user, tour=tour).first().isPaid
                response.append(
                    {
                        'id': tour.id,
                        'name': tour.name,
                        'description': tour.description,
                        'price': tour.price,
                        'seats': tour.seats,
                        'isActive': tour.isActive,
                        'image': image,
                        'arrivalDate': tour.arrivalDate,
                        'departureDate': tour.departureDate,
                        'isPaid': isPaid
                    }
                )
            return response

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class YooMooneyPaidSerializer(serializers.Serializer):
    label = serializers.CharField(required=True)

    def create(self, validated_data):
        try:
            label = json.loads(validated_data['label'])
            if label.tour and label.user:
                if User.objects.filter(id=label.user).exists():
                    user = User.objects.filter(id=label.user).first()
                    if UserTour.objects.filter(user=user, tour=label.tour).exists():
                        userTour = UserTour.objects.filter(user=user, tour=label.tour).first()
                        userTour.isPaid = True
                        userTour.save()
                        return {
                            'success': True,
                            'message': 'Pay successful'
                        }

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e



class AllUserInToursSerializer(serializers.Serializer):
    def create(self, validated_data):
        try:
            if validated_data['id']:
                if Tour.objects.filter(id=validated_data['id']).exists():
                    tour = Tour.objects.filter(id=validated_data['id']).first()

                    user_tours = UserTour.objects.filter(tour=tour)
                    response = []
                    for user_tour in user_tours:
                        user = user_tour.user
                        response.append({
                            'first_name': user.first_name,
                            'last_name': user.last_name,
                            'id': user.id,
                            'email': user.email,
                            'isPaid': user_tour.isPaid,
                        })

                    return response
            raise exceptions.NotFound("Tour not found")

        except Exception as e:
            if not issubclass(e.__class__, exceptions.APIException):
                raise exceptions.APIException(str(e))
            raise e


